package org.kumas.sgrpc.rpc;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.kumas.sgrpc.common.Experimental;


public interface Result extends Serializable {

    Object getValue();
    void setValue(Object value);
    Throwable getException();

    void setException(Throwable t);
    boolean hasException();
    Object recreate() throws Throwable;
    Map<String, String> getAttachments();
    @Experimental("Experiment api for supporting Object transmission")
    Map<String, Object> getObjectAttachments();
    @Experimental("Experiment api for supporting Object transmission")
    void addObjectAttachments(Map<String, Object> map);
    void addAttachments(Map<String, String> map);
    void setAttachments(Map<String, String> map);
    @Experimental("Experiment api for supporting Object transmission")
    void setObjectAttachments(Map<String, Object> map);
    @Experimental("Experiment api for supporting Object transmission")
    Object getObjectAttachment(String key);
    String getAttachment(String key);
    String getAttachment(String key, String defaultValue);
    @Experimental("Experiment api for supporting Object transmission")
    Object getObjectAttachment(String key, Object defaultValue);
    void setAttachment(String key, String value);
    Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn);
    @Experimental("Experiment api for supporting Object transmission")
    void setAttachment(String key, Object value);

    @Experimental("Experiment api for supporting Object transmission")
    void setObjectAttachment(String key, Object value);
    <U> CompletableFuture<U> thenApply(Function<Result, ? extends U> fn);

    Result get() throws InterruptedException, ExecutionException;

    Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}